EC2 + Docker Machine + Swarm + Composeでコンテナオーケストレーションする
はじめに
今回はDocker Machine、Docker Swarm、Docker Composeの3つを使って、Amazon EC2でDockerコンテナをオーケストレーションしてみます!
やってみた
Swarmクラスタを作成する
まずは前回と同様に、Docker MachineでSwarmクラスタを作成します。
なおswarm createではdiscovery-stage.hub.docker.comにリクエストしてクラスタIDを取得しているのですが、タイミングによってはエラーが出る事がありました。現在はベータリリースという扱いなので仕方がないかと思いますが、ちょっと注意が必要です。
$ sudo docker run --rm swarm create 4e8ebb66a08f838fe05a36c20341f044 $ sudo ./docker-machine create --driver amazonec2 --amazonec2-access-key YOUR_ACCESS_KEY --amazonec2-secret-key YOUR_SECRET_KEY --amazonec2-region ap-northeast-1 --amazonec2-ami ami-a1bf56a1 --amazonec2-vpc-id YOUR_VPC_ID--swarm --swarm-master --swarm-discovery token://4e8ebb66a08f838fe05a36c20341f044 master $ sudo ./docker-machine create --driver amazonec2 --amazonec2-access-key YOUR_ACCESS_KEY --amazonec2-secret-key YOUR_SECRET_KEY--amazonec2-region ap-northeast-1 --amazonec2-ami ami-a1bf56a1 --amazonec2-vpc-id YOUR_VPC_ID--swarm --swarm-discovery token://4e8ebb66a08f838fe05a36c20341f044 node1 $ sudo ./docker-machine create --driver amazonec2 --amazonec2-access-key YOUR_ACCESS_KEY --amazonec2-secret-key YOUR_SECRET_KEY --amazonec2-region ap-northeast-1 --amazonec2-ami ami-a1bf56a1 --amazonec2-vpc-id YOUR_VPC_ID--swarm --swarm-discovery token://4e8ebb66a08f838fe05a36c20341f044 node2
作成されたSwarmクラスタはこんな感じ。EC2インスタンスが3台追加されているはずです。
$ sudo ./docker-machine ls NAME ACTIVE DRIVER STATE URL SWARM master amazonec2 Running tcp://54.178.132.195:2376 master (master) node1 amazonec2 Running tcp://54.92.24.244:2376 master node2 * amazonec2 Running tcp://54.178.180.56:2376 master
Docker Composeをインストールする
Docker Composeはバイナリをダウンロードしてくるだけです。
$ curl -L https://github.com/docker/compose/releases/download/1.1.0/docker-compose-`uname -s`-`uname -m` > docker-compose $ sudo mv ./docker-compose /usr/local/bin $ sudo chmod +x /usr/local/bin/docker-compose $ docker-compose --version docker-compose 1.1.0
オーケストレーションするDockerコンテナイメージを作成する
今回はWebサーバとMemcachedサーバを構築し、Memcachedにカウンター値を格納して、Webサーバにアクセスするたびにカウントアップする、という仕組みを作ります。このためWebアプリケーションを搭載したWebサーバ用のDockerイメージを作成します。
compose/web/scriptsというディレクトリを作り、その中にWebアプリケーションとなるRubyスクリプトを作成します。
$ mkdir ~/compose/web/scripts $ vi ~/compose/web/scripts/app.rb
スクリプトの内容はこんな感じ。SinatraでWebサーバとして動作し、DalliによってMemcachedを操作します。Memcachedサーバは固定値を使っています(後述にて説明します)
require 'sinatra' require 'dalli' set :environment, :production dc = Dalli::Client.new('54.178.132.195:11211') value = Array.new get '/' do if dc.get("count") == nil then dc.set("count", 1) end value = dc.get("count") dc.set("count", value + 1) "count is " + value.to_s end
Webサーバ用DockerイメージのDockerfileでは、Docker Language Stackのrubyを使い、gemでSinatraとDalliを追加し、上述のrubyスクリプトを組み込んで起動しています。またSinatraのデフォルトポートである4567をEXPOSEしています。
$ vi ~/compose/web/Dockerfile FROM ruby:latest RUN gem install sinatra RUN gem install dalli ADD scripts/app.rb /usr/local/bin/app.rb CMD ["ruby","/usr/local/bin/app.rb"] EXPOSE 4567
このDockerfileをbuildし、Docker Hubに登録しておきます。
$ sudo docker build -t smokeymonkey/app . $ sudo docker login $ sudo docker push smokeymonkey/app:latest
Docker Composeの定義ファイルを作成する
Docker Domposeはdocker-compose.ymlファイルに定義を記述します。今回はwebコンテナとmemcachedコンテナを定義しており、Webコンテナでは前述で作成したWebサーバ用Dockerイメージを指定しています。
$ cd ~/compose/ $ vi docker-compose.yml web: image: smokeymonkey/app:latest ports: - 4567 memcached: image: memcached ports: - 11211:11211 environment: - constraint:node==master
memcachedコンテナはconstraint:node行によって必ずmasterノードで起動するように定義しています。これが上述のRubyスクリプトでMemcachedサーバのIPアドレスを固定値として埋め込んでいた理由です。
また、この仕組みでは11211/tcpとコンテナの4567/tcpポートがバインドされるランダムなホスト側ポートを使いますので、セキュリティグループで許可してください。
コンテナオーケストレーションする
さて本題。まず、Swarmクラスタを操作するために、環境変数を定義します。
$ $(sudo ./docker-machine env --swarm master)
次にComposeを操作するための環境変数の定義です。環境変数DOCKER_CLIENT_TIMEOUTはデフォルトでは60秒なのですが、大きなサイズのコンテナイメージを使う場合すぐにタイムアウトしてしまうので、大きく取っておきます。
$ export DOCKER_CLIENT_TIMEOUT=600
では起動!
$ sudo -E /usr/local/bin/docker-compose up -d Creating compose_web_1... Creating compose_memcached_1... $ sudo -E /usr/local/bin/docker-compose ps Name Command State Ports ------------------------------------------------------------------------------------------ compose_memcached_1 memcached Up 54.178.132.195:11211->11211/tcp compose_web_1 ruby /usr/local/bin/app.rb Up 54.92.24.244:49153->4567/tcp
memcachedコンテナとweb_1コンテナが起動しました。試しにweb_1コンテナにアクセスしてみます。
$ curl 54.92.24.244:49153 count is 1
ちゃんとカウントが取れてますね。
コンテナをスケールアップさせる
それではオーケストレーションのキモ、コンテナをスケールさせてみます。
$ sudo -E /usr/local/bin/docker-compose scale web=5 Creating compose_web_2... Creating compose_web_3... Creating compose_web_4... Creating compose_web_5... Starting compose_web_2... Starting compose_web_3... Starting compose_web_4... Starting compose_web_5...
一気に4つのコンテナが増えました。確認してみます。
$ sudo -E /usr/local/bin/docker-compose ps Name Command State Ports ------------------------------------------------------------------------------------------ compose_memcached_1 memcached Up 54.178.132.195:11211->11211/tcp compose_web_1 ruby /usr/local/bin/app.rb Up 54.92.24.244:49153->4567/tcp compose_web_2 ruby /usr/local/bin/app.rb Up 54.178.132.195:49155->4567/tcp compose_web_3 ruby /usr/local/bin/app.rb Up 54.178.180.56:49154->4567/tcp compose_web_4 ruby /usr/local/bin/app.rb Up 54.92.24.244:49156->4567/tcp compose_web_5 ruby /usr/local/bin/app.rb Up 54.92.24.244:49157->4567/tcp
Swarmノードに分散されて、Webコンテナが5つに増えています!
カウンタの動作を確認してみます。
$ curl 54.178.132.195:49155 count is 2 $ curl 54.178.180.56:49154 count is 3 $ curl 54.92.24.244:49156 count is 4 $ curl 54.92.24.244:49157 count is 5
問題なく、どのWebサーバにアクセスしても、カウントがアップされていますね!
コンテナをスケールダウンさせる
スケールダウンもコマンド一発でできます。
$ sudo -E /usr/local/bin/docker-compose scale web=1 Stopping compose_web_5... Stopping compose_web_4... Stopping compose_web_3... Stopping compose_web_2... Removing compose_web_5... Removing compose_web_4... Removing compose_web_3... Removing compose_web_2... $ sudo -E /usr/local/bin/docker-compose ps Name Command State Ports ------------------------------------------------------------------------------------------ compose_memcached_1 memcached Up 54.178.132.195:11211->11211/tcp compose_web_1 ruby /usr/local/bin/app.rb Up 54.92.24.244:49153->4567/tcp
簡単!
さいごに
まだまだベータリリースなので少々動作に気になる点はありますが(特にAPIサーバ側)、かなり楽に展開できました。こうなると今後のECSの展開が気になるところですねー。正式リリースが楽しみです。